

#include <Application.h>


Application::Application()
{
	mIsMouseLButtonDown = false;
	mWindow = new Window();
	mKeys = new bool[256];
	for(int i=0;i<256;i++)
		mKeys[i] = false;
}

Application::~Application()
{
	delete[] mKeys;
	mKeys = NULL;
	delete mWindow;
}

void Application::Initialize(HINSTANCE hInstance)
{
	mHinstance = hInstance;
	mWindow->mWindowRect->left = 0;
	mWindow->mWindowRect->right = 640;
	mWindow->mWindowRect->top = 0;
	mWindow->mWindowRect->bottom = 480;
	mWindow->mTitle = new char[15];
	for(int i=0;i<15;i++)
		mWindow->mTitle[i] = '\0';
	char title[] = "Color Window";
	strcpy_s(mWindow->mTitle,sizeof(title), title); 
	mWindow->mBits = 16;
	mWindow->mFullScreen = false;
	
}



bool Application::CreateGLWindow(HINSTANCE inHinstance, WNDPROC inWndProc)
{
	GLuint pixelFormat;
	WNDCLASS wc;
	DWORD		dwExStyle;
	DWORD		dwStyle;
	memset(&wc,0,sizeof(WNDCLASS));
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc	= (WNDPROC)inWndProc;
	wc.cbClsExtra	= 0;
	wc.cbWndExtra = 0;
	wc.hInstance = inHinstance;
	wc.hIcon	= LoadIcon(NULL, IDI_WINLOGO);
	wc.hCursor	= LoadCursor(NULL, IDC_ARROW);	
	wc.hbrBackground	= NULL;
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= mWindow->mTitle;

	RegisterClass(&wc);

	dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
	dwStyle=WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS |WS_CLIPCHILDREN;

	mWindow->mHwnd = CreateWindowEx(dwExStyle,mWindow->mTitle,mWindow->mTitle,dwStyle,0,0,mWindow->mWindowRect->right - mWindow->mWindowRect->left,
		mWindow->mWindowRect->bottom - mWindow->mWindowRect->top,NULL,NULL,mHinstance,NULL);

	static	PIXELFORMATDESCRIPTOR pfd=				// pfd Tells Windows How We Want Things To Be
	{
		sizeof(PIXELFORMATDESCRIPTOR),				// Size Of This Pixel Format Descriptor
		1,											// Version Number
		PFD_DRAW_TO_WINDOW |						// Format Must Support Window
		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL
		PFD_DOUBLEBUFFER,							// Must Support Double Buffering
		PFD_TYPE_RGBA,								// Request An RGBA Format
		mWindow->mBits,										// Select Our Color Depth
		0, 0, 0, 0, 0, 0,							// Color Bits Ignored
		0,											// No Alpha Buffer
		0,											// Shift Bit Ignored
		0,											// No Accumulation Buffer
		0, 0, 0, 0,									// Accumulation Bits Ignored
		16,											// 16Bit Z-Buffer (Depth Buffer)  
		0,											// No Stencil Buffer
		0,											// No Auxiliary Buffer
		PFD_MAIN_PLANE,								// Main Drawing Layer
		0,											// Reserved
		0, 0, 0										// Layer Masks Ignored
	};

	mWindow->mHdc = GetDC(mWindow->mHwnd);
	pixelFormat = ChoosePixelFormat(mWindow->mHdc,&pfd);

	SetPixelFormat(mWindow->mHdc,pixelFormat,&pfd);

	mWindow->mHrc = wglCreateContext(mWindow->mHdc);

	wglMakeCurrent(mWindow->mHdc,mWindow->mHrc);

	bool result = mGLInfo.getInfo();

	ShowWindow(mWindow->mHwnd,SW_SHOW);						// Show The Window
	SetForegroundWindow(mWindow->mHwnd);						// Slightly Higher Priority
	SetFocus(mWindow->mHwnd);									// Sets Keyboard Focus To The Window

	return true;
}

GLvoid Application::ReSizeGLScene(GLsizei inWidth, GLsizei inHeight)		// Resize And Initialize The GL Window
{
	if (inHeight==0)										// Prevent A Divide By Zero By
	{
		inHeight=1;										// Making Height Equal One
	}

	glViewport(0,0,inWidth,inHeight);						// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();									// Reset The Projection Matrix

	// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0f,(GLfloat)inWidth/(GLfloat)inHeight,0.1f,1000.0f);

	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
	glLoadIdentity();									// Reset The Modelview Matrix
	
}

LRESULT CALLBACK Application::WndProc(	HWND	hWnd,UINT	uMsg,WPARAM	wParam,	LPARAM	lParam)			
{
	switch (uMsg)									// Check For Windows Messages
	{
		case WM_ACTIVATE:							// Watch For Window Activate Message
		{
			if (!HIWORD(wParam))					// Check Minimization State
			{
				mWindow->mActive = TRUE;						// Program Is Active
			}
			else
			{
				mWindow->mActive = FALSE;						// Program Is No Longer Active
			}
			return 0;								// Return To The Message Loop
		}

		case WM_SYSCOMMAND:							// Intercept System Commands
		{
			switch (wParam)							// Check System Calls
			{
				case SC_SCREENSAVE:					// Screensaver Trying To Start?
				case SC_MONITORPOWER:				// Monitor Trying To Enter Powersave?
				return 0;							// Prevent From Happening
			}
			break;									// Exit
		}

		case WM_LBUTTONDOWN:
			mIsMouseLButtonDown = true;
			break;
		case WM_LBUTTONUP:
			mIsMouseLButtonDown = false;
			break;
		case WM_CLOSE:								// Did We Receive A Close Message?
		{
			PostQuitMessage(0);						// Send A Quit Message
			return 0;								// Jump Back
		}

		case WM_KEYDOWN:							// Is A Key Being Held Down?
		{
			mKeys[wParam] = TRUE;					// If So, Mark It As TRUE
			break;//return 0;								// Jump Back
		}

	

		case WM_KEYUP:								// Has A Key Been Released?
		{
			mKeys[wParam] = FALSE;					// If So, Mark It As FALSE
			break;//return 0;								// Jump Back
		}

		
		case WM_SIZE:								// Resize The OpenGL Window
		{
			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
			return 0;								// Jump Back
		}
	}

	// Pass All Unhandled Messages To DefWindowProc
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

void Application::UpdateMousePosition()
{
	GetCursorPos( &mMouseCurPosition );
	ScreenToClient( mWindow->mHwnd, &mMouseCurPosition );
}

void Application::UpdateDeltaTime()
{
	mCurrentTime = timeGetTime();
	mDeltaTime = (float)(mCurrentTime - mLastTime)* 0.001f;
	mLastTime = mCurrentTime;
}


GLvoid Application::KillGLWindow()								// Properly Kill The Window
{

	if (mWindow->mHrc)											// Do We Have A Rendering Context?
	{
		wglMakeCurrent(NULL,NULL);					// Are We Able To Release The DC And RC Contexts?
		
		wglDeleteContext(mWindow->mHrc);						// Are We Able To Delete The RC?
		
		mWindow->mHrc = NULL;										// Set RC To NULL
	}

	ReleaseDC(mWindow->mHwnd,mWindow->mHdc);					// Are We Able To Release The DC
		mWindow->mHdc = NULL;										// Set DC To NULL
	

	if(mWindow->mHwnd)
	{
		DestroyWindow(mWindow->mHwnd);
		mWindow->mHwnd = NULL;										// Set hWnd To NULL
	}

	UnregisterClass(mWindow->mTitle,mHinstance);			// Are We Able To Unregister Class
	mHinstance = NULL;
}
